See also http://www.flounder.com/validating_edit_control.htmCode
//##############################################################################
// Edit Control subclass callback function
//##############################################################################
LRESULT CALLBACK float_edit_subclass(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
int shift = (GetKeyState(VK_SHIFT) < 0) ? SHFT : 0;
int control = (GetKeyState(VK_CONTROL) < 0) ? CTRL : 0;
int my_id = GetWindowLong(hwnd, GWL_ID);
HWND parent = GetParent(hwnd);
DWORD selection;
int start;
int finish;
switch(message) {
case WM_CHAR:
// valid characters fall through to original window proc, invalid characters
// return a FALSE which prevents processing.
// if (wparam == 0x16) return FALSE; // control-v
if (wparam == 0x03) break; // control-c
if (wparam == 0x08) break; // control-h (backspace)
if (wparam == 0x18) break; // control-x
if (wparam >= '0' && wparam <= '9') break;
if (wparam == '.') {
char buffer[100];
GetWindowText(hwnd, buffer, 99);
if (strrchr(buffer, '.') == NULL) break;
}
if (wparam == '-') {
selection = Edit_GetSel(hwnd);
start = LOWORD(selection);
finish = HIWORD(selection);
if (start == 0) break;
}
return FALSE;
break;
case WM_KEYDOWN:
switch(wparam + control + shift) {
case VK_ESCAPE:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_ABORT_EDIT), (LPARAM)hwnd);
return TRUE;
case VK_F2:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_END_EDIT), (LPARAM)hwnd);
return TRUE;
case VK_RETURN:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_COL_RIGHT), (LPARAM)hwnd);
return TRUE;
case CTRL + VK_HOME:
case CTRL + VK_UP:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_FIRST_ROW), (LPARAM)hwnd);
return TRUE;
break;
case CTRL + VK_END:
case CTRL + VK_DOWN:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_LAST_ROW), (LPARAM)hwnd);
return TRUE;
break;
case VK_UP:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_ROW_UP), (LPARAM)hwnd);
return TRUE;
break;
case VK_DOWN:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_ROW_DOWN), (LPARAM)hwnd);
return TRUE;
break;
case VK_NEXT:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_PAGE_DOWN), (LPARAM)hwnd);
return TRUE;
break;
case VK_PRIOR:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_PAGE_UP), (LPARAM)hwnd);
return TRUE;
break;
case VK_TAB:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_COL_RIGHT), (LPARAM)hwnd);
return TRUE;
break;
case SHFT + VK_TAB:
SendMessage(parent, WM_COMMAND, MAKEWPARAM(my_id, EN_COL_LEFT), (LPARAM)hwnd);
return TRUE;
break;
case CTRL + VK_TAB:
case SHFT + CTRL + VK_TAB:
// control-tab and control-shift-tab are forwarded to the parent,
SendMessage(parent, message, wparam, lparam);
return TRUE;
break;
}
}
// call the original window function for anything we don't care to deal with.
return CallWindowProc((WNDPROC)GetWindowLong(hwnd, GWL_USERDATA), hwnd, message, wparam, lparam);
}